package com.ml4ai.backend.services.impl;

import com.ml4ai.backend.services.EsService;
import com.ml4ai.core.stack.elasticsearch.ElasticSearchAgent;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * Created by leecheng on 2018/10/13.
 */
@Slf4j
@Service
public class EsServiceImpl implements EsService {

    @Value("${elasticsearch.servers}")
    private String esServers;

    @Value("${elasticsearch.cluster}")
    private String esCluster;

    private TransportClient client;

    @PostConstruct
    private void getClient() throws Exception {
        client = ElasticSearchAgent.builder().esCluster(esCluster).esServers(esServers).build().getClient();
    }

    @Override
    public boolean putJson(String index, String type, String id, Map<String, Object> document) {
        try {
            IndexResponse response = client.prepareIndex(index, type, id).setSource(document, XContentType.JSON).get();
            return response != null;
        } catch (Exception e) {
            log.error("{}", e);
            return false;
        }
    }

    @Override
    public boolean deleteDocument(String index, String type, String id) {
        return client.prepareDelete(index, type, id).get() != null;
    }

    public List<Map<String, Object>> queryBool(String[] indices, String[] types, Map<String, Object> queryMap, int offset, int limit) {
        BoolQueryBuilder bool = QueryBuilders.boolQuery();
        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(indices).setTypes(types);
        searchRequestBuilder.setFrom(offset);
        if (limit > 0) {
            searchRequestBuilder.setSize(limit);
        }
        queryMap.entrySet().forEach(entry -> {
            String key = entry.getKey();
            Object val = entry.getValue();
            String[] parts = key.split(" ");
            String oper = "term";
            if (parts.length > 1) {
                oper = parts[1];
            }
            String field = parts[0];
            switch (oper) {
                case "=":
                case "term":
                    bool.must(QueryBuilders.termQuery(field, val));
                    break;
                case "fuzzy":
                    if (val instanceof String) {
                        bool.must(QueryBuilders.fuzzyQuery(field, (String) val));
                    } else {
                        bool.must(QueryBuilders.fuzzyQuery(field, val));
                    }
                    break;
                default:
                    throw new IllegalStateException(String.format("非法标识:[" + oper + "]"));
            }
        });
        Iterator<SearchHit> hits = searchRequestBuilder.setQuery(bool).get().getHits().iterator();
        List<Map<String, Object>> list = new ArrayList<>();
        while (hits.hasNext()) {
            Map<String,Object> map = new HashMap<>();
            SearchHit hit = hits.next();
            map.putAll(hit.getSourceAsMap());
            map.put("id",hit.getId());
            list.add(map);
        }
        return list;
    }
}
